// ==UserScript==
// @name         招投标公司信息自动填写
// @namespace    https://gtjs-9gjbu0mx.maozi.io/2025/10/10/you-hou-biao-shu/
// @version      1.2
// @description  招投标公司信息自动填写+可视化设置+动态公司管理+导入导出（单菜单版·顺序调整）
// @author       You
// @match        *://zxgk.court.gov.cn/shixin/*
// @match        *://www.ccgp.gov.cn/cr/list*
// @match        *://www.creditchina.gov.cn/zhuanxiangchaxun/zhongdashuishouweifaanjian/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @run-at       document-end
// @updateURL    https://gtjs-9gjbu0mx.maozi.io/user-scripts/biaoshu.user.js
// ==/UserScript==

(function () {
    'use strict';

    /* ================= 1. 默认数据 ================= */
    const DEFAULT_COMPANIES = [
        { id: 1, name: '山西A有限公司', code: '1111111111111111' },
        { id: 2, name: '山西B股份有限公司', code: '1111111111111111' }
    ];
    const DEFAULT_TARGET_ID = 1;
    const DEFAULT_SITES = [
        { url: 'https://zxgk.court.gov.cn/shixin/', nameSel: '#pName', codeSel: '#pCardNum', btnSel: '', siteName: '失信被执行人查询网' },
        { url: 'https://www.ccgp.gov.cn/cr/list', nameSel: '#orgName', codeSel: '', btnSel: '#searchForm', siteName: '中国政府采购网' },
        { url: 'https://www.creditchina.gov.cn/zhuanxiangchaxun/zhongdashuishouweifaanjian/', nameSel: 'div.searchBox > input:nth-of-type(1)', codeSel: '', btnSel: 'span.infoCheckBtn', siteName: '信用中国-重大税收违法失信主体' }
    ];

    /* ================= 2. 数据存取 ================= */
    function getCompanies() {
        const saved = GM_getValue('bid_script_company_list');
        if (saved && Array.isArray(saved) && saved.length) return saved;
        saveCompanies(DEFAULT_COMPANIES);
        return DEFAULT_COMPANIES;
    }
    function saveCompanies(list) { GM_setValue('bid_script_company_list', list); }
    function getTargetId() {
        const id = GM_getValue('bid_script_target_id');
        const companies = getCompanies();
        if (id && companies.some(c => c.id === id)) return id;
        const fallback = companies.length ? companies[0].id : DEFAULT_TARGET_ID;
        GM_setValue('bid_script_target_id', fallback);
        return fallback;
    }
    function getNextId() {
        return Math.max(...getCompanies().map(c => c.id), 0) + 1;
    }

    /* ================= 3. 站点匹配 ================= */
    const baseMarker = 'tampermonkey_bid_script_executed';
    let siteConfig = null;
    (function () {
        const url = window.location.href;
        siteConfig = DEFAULT_SITES.find(s => url.includes(s.url)) || null;
        if (!siteConfig) console.log('[信息] 未匹配到站点，脚本仅注册菜单。');
    })();

    const siteExclusiveMarker = siteConfig ? `${baseMarker}_${siteConfig.siteName}` : null;
    if (siteExclusiveMarker && sessionStorage.getItem(siteExclusiveMarker)) {
        console.log('[信息] 本页已执行过，跳过自动填充。');
        window.skipAutoFill = true;
    } else {
        if (siteExclusiveMarker) sessionStorage.setItem(siteExclusiveMarker, Date.now());
        window.skipAutoFill = false;
    }

    /* ================= 4. 工具函数 ================= */
    const log = (content, type = 'info') => {
        const pre = { info: '[信息]', success: '[🟢成功]', warn: '[⚠️警告]', error: '[🔴错误]' };
        console.log(`${pre[type] || pre.info} ${content}`);
    };
    function getTargetCompany() {
        const id = getTargetId();
        const companies = getCompanies();
        const c = companies.find(i => i.id === id);
        if (c) log(`目标公司：${c.name}`);
        else log('目标公司不存在', 'error');
        return c || null;
    }
    function waitForElement(selector, timeout = 10000) {
        return new Promise((resolve, reject) => {
            const el = document.querySelector(selector);
            if (el) return resolve(el);
            const ob = new MutationObserver(() => {
                const el = document.querySelector(selector);
                if (el) { ob.disconnect(); resolve(el); }
            });
            ob.observe(document.body, { childList: true, subtree: true });
            setTimeout(() => { ob.disconnect(); reject(new Error(`未找到 ${selector}`)); }, timeout);
        });
    }

    /* ================= 5. 自动填充 ================= */
    async function fillInfo() {
        if (window.skipAutoFill || !siteConfig) return;
        log('开始填充信息...');
        const company = getTargetCompany();
        if (!company) return;
        try {
            const nameInput = await waitForElement(siteConfig.nameSel);
            nameInput.value = company.name;
            nameInput.dispatchEvent(new Event('change', { bubbles: true }));
            nameInput.dispatchEvent(new Event('input', { bubbles: true }));
            if (siteConfig.codeSel) {
                const codeInput = await waitForElement(siteConfig.codeSel);
                codeInput.value = company.code;
                codeInput.dispatchEvent(new Event('change', { bubbles: true }));
                codeInput.dispatchEvent(new Event('input', { bubbles: true }));
            }
            if (siteConfig.btnSel) {
                const btn = await waitForElement(siteConfig.btnSel);
                setTimeout(() => btn.click(), 300);
            }
            log('信息填充完成');
        } catch (e) { log(e.message, 'error'); }
    }
    fillInfo();

    /* ================= 6. 可视化面板 ================= */
    function createSettingsPanel() {
        const exist = document.getElementById('bid-script-settings-panel');
        if (exist) exist.remove();

        const overlay = document.createElement('div');
        overlay.id = 'bid-script-settings-panel';
        overlay.style.cssText = `position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);z-index:9999;display:flex;justify-content:center;align-items:center;`;
        const panel = document.createElement('div');
        panel.style.cssText = `background:#fff;padding:20px;border-radius:8px;width:90%;max-width:900px;max-height:80vh;overflow-y:auto;box-shadow:0 0 15px rgba(0,0,0,.3);font-family:sans-serif;`;
        panel.innerHTML = `
            <h2 style="margin-top:0;color:#333;border-bottom:1px solid #eee;padding-bottom:10px;">招投标脚本 – 设置中心</h2>

            <!-- ① 选择目标公司 -->
            <div style="margin-bottom:20px;">
                <h3>1. 选择目标公司</h3>
                <select id="company-select" style="width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;margin-bottom:10px;">
                    ${getCompanies().map(c => `<option value="${c.id}" ${getTargetId() === c.id ? 'selected' : ''}>${c.name}</option>`).join('')}
                </select>
                <p style="color:#666;font-size:12px;">当前信用代码：<strong id="current-code">${getTargetCompany()?.code || 'N/A'}</strong></p>
            </div>

            <!-- ② 清除标记并刷新 -->
            <div style="margin-bottom:20px;border-top:1px solid #eee;padding-top:15px;">
                <h3>2. 清除标记并刷新</h3>
                <button id="clear-mark-reload" style="padding:8px 15px;background:#f44336;color:#fff;border:none;border-radius:4px;cursor:pointer;">清除本页执行标记并刷新</button>
                <p style="color:#666;font-size:12px;margin-top:8px;">若本页已自动填充过，点击后可让脚本再次运行。</p>
            </div>

            <!-- ③ 公司管理 -->
            <div style="margin-bottom:20px;border-top:1px solid #eee;padding-top:15px;">
                <h3>3. 公司管理</h3>
                <div style="margin-bottom:10px;">
                    <button id="add-company-btn" style="padding:6px 12px;background:#4CAF50;color:#fff;border:none;border-radius:4px;cursor:pointer;margin-right:5px;">添加新公司</button>
                    <button id="export-companies-btn" style="padding:6px 12px;background:#2196F3;color:#fff;border:none;border-radius:4px;cursor:pointer;margin-right:5px;">导出列表</button>
                    <input type="file" id="import-companies-input" accept=".json" style="display:none;">
                    <button id="import-companies-btn" style="padding:6px 12px;background:#FF9800;color:#fff;border:none;border-radius:4px;cursor:pointer;">导入列表</button>
                </div>
                <div style="border:1px solid #ddd;border-radius:4px;overflow:hidden;">
                    <table id="companies-table" style="width:100%;border-collapse:collapse;font-size:14px;">
                        <thead><tr style="background:#f2f2f2;">
                            <th style="padding:8px;text-align:left;border-bottom:1px solid #ddd;">ID</th>
                            <th style="padding:8px;text-align:left;border-bottom:1px solid #ddd;">公司名称</th>
                            <th style="padding:8px;text-align:left;border-bottom:1px solid #ddd;">统一社会信用代码</th>
                            <th style="padding:8px;text-align:center;border-bottom:1px solid #ddd;width:120px;">操作</th>
                        </tr></thead>
                        <tbody></tbody>
                    </table>
                </div>
            </div>

            <div style="margin-top:20px;display:flex;justify-content:flex-end;">
                <button id="close-panel" style="padding:8px 15px;background:#999;color:#fff;border:none;border-radius:4px;cursor:pointer;">关闭</button>
            </div>
        `;
        overlay.appendChild(panel);
        document.body.appendChild(overlay);

        /* ---------- 绑定事件 ---------- */
        const companySelect = panel.querySelector('#company-select');
        const currentCode = panel.querySelector('#current-code');
        const closeBtn = panel.querySelector('#close-panel');
        const clearBtn = panel.querySelector('#clear-mark-reload');
        const addBtn = panel.querySelector('#add-company-btn');
        const exportBtn = panel.querySelector('#export-companies-btn');
        const importBtn = panel.querySelector('#import-companies-btn');
        const importInput = panel.querySelector('#import-companies-input');
        const tableBody = panel.querySelector('#companies-table tbody');

        function renderTable() {
            const companies = getCompanies();
            tableBody.innerHTML = companies.map(c => `
                <tr>
                    <td style="padding:8px;border-bottom:1px solid #ddd;">${c.id}</td>
                    <td style="padding:8px;border-bottom:1px solid #ddd;">${c.name}</td>
                    <td style="padding:8px;border-bottom:1px solid #ddd;font-family:monospace;font-size:13px;">${c.code}</td>
                    <td style="padding:8px;border-bottom:1px solid #ddd;text-align:center;">
                        <button class="edit-company" data-id="${c.id}" style="margin-right:3px;padding:3px 8px;background:#2196F3;color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:12px;">编辑</button>
                        <button class="delete-company" data-id="${c.id}" style="padding:3px 8px;background:#f44336;color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:12px;">删除</button>
                    </td>
                </tr>
            `).join('');
            tableBody.querySelectorAll('.edit-company').forEach(btn => {
                btn.onclick = () => editCompany(parseInt(btn.dataset.id));
            });
            tableBody.querySelectorAll('.delete-company').forEach(btn => {
                btn.onclick = () => deleteCompany(parseInt(btn.dataset.id));
            });
        }
        renderTable();

        companySelect.onchange = () => {
            const id = parseInt(companySelect.value);
            GM_setValue('bid_script_target_id', id);
            const c = getCompanies().find(i => i.id === id);
            currentCode.textContent = c ? c.code : 'N/A';
            log(`已切换目标公司ID → ${id}`);
        };

        closeBtn.onclick = () => overlay.remove();
        overlay.onclick = e => { if (e.target === overlay) overlay.remove(); };

        clearBtn.onclick = () => {
            if (!siteConfig) return alert('当前页面不在匹配列表，无需清除。');
            sessionStorage.removeItem(siteExclusiveMarker);
            alert('执行标记已清除，页面将刷新！');
            window.location.reload();
        };

        addBtn.onclick = () => {
            const name = prompt('新公司名：');
            if (!name) return;
            const code = prompt('统一社会信用代码：');
            if (!code) return;
            const companies = getCompanies();
            const newC = { id: getNextId(), name: name.trim(), code: code.trim() };
            companies.push(newC);
            saveCompanies(companies);
            renderTable();
            companySelect.innerHTML = companies.map(c => `<option value="${c.id}" ${getTargetId() === c.id ? 'selected' : ''}>${c.name}</option>`).join('');
            currentCode.textContent = newC.code;
            alert('添加成功！');
        };

        function editCompany(id) {
            const companies = getCompanies();
            const c = companies.find(i => i.id === id);
            if (!c) return;
            const newName = prompt('编辑公司名：', c.name);
            if (newName === null) return;
            const newCode = prompt('编辑信用代码：', c.code);
            if (newCode === null) return;
            c.name = newName.trim();
            c.code = newCode.trim();
            saveCompanies(companies);
            renderTable();
            companySelect.innerHTML = companies.map(c => `<option value="${c.id}" ${getTargetId() === c.id ? 'selected' : ''}>${c.name}</option>`).join('');
            if (getTargetId() === id) currentCode.textContent = c.code;
            alert('已更新！');
        }

        function deleteCompany(id) {
            const companies = getCompanies();
            const idx = companies.findIndex(i => i.id === id);
            if (idx === -1) return;
            if (!confirm(`确定删除“${companies[idx].name}”？`)) return;
            companies.splice(idx, 1);
            saveCompanies(companies);
            if (id === getTargetId() && companies.length) GM_setValue('bid_script_target_id', companies[0].id);
            renderTable();
            companySelect.innerHTML = companies.map(c => `<option value="${c.id}" ${getTargetId() === c.id ? 'selected' : ''}>${c.name}</option>`).join('');
            currentCode.textContent = getTargetCompany()?.code || 'N/A';
            alert('已删除！');
        }

        exportBtn.onclick = () => {
            const dataStr = JSON.stringify(getCompanies(), null, 2);
            const blob = new Blob([dataStr], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `招投标公司列表_${new Date().toISOString().slice(0, 10)}.json`;
            a.click();
            URL.revokeObjectURL(url);
        };

        importBtn.onclick = () => {
            if (!confirm('导入会覆盖现有全部公司，确定继续？')) return;
            importInput.click();
        };
        importInput.onchange = e => {
            const file = e.target.files[0];
            if (!file) return;
            const reader = new FileReader();
            reader.onload = ev => {
                try {
                    const arr = JSON.parse(ev.target.result);
                    if (!Array.isArray(arr) || !arr.every(i => i.id && i.name && i.code)) throw new Error('格式错误');
                    saveCompanies(arr);
                    GM_setValue('bid_script_target_id', arr[0].id);
                    renderTable();
                    companySelect.innerHTML = arr.map(c => `<option value="${c.id}" selected>${c.name}</option>`).join('');
                    currentCode.textContent = arr[0].code;
                    alert('导入成功！');
                } catch (err) { alert('导入失败：' + err.message); }
            };
            reader.readAsText(file);
            importInput.value = '';
        };
    }

    /* ================= 7. 仅注册一个菜单 ================= */
    GM_registerMenuCommand('⚙️ 设置', createSettingsPanel);
})();